【TS技巧】通过对象推导出联合类型

首先,我们给出下面👇🏻这段代码,
fruitCount的每个属性值类型都是number,我们期望由它衍生出一个singleFruitCount对象export const fruitCount = { apple: 1, pear: 4, banana: 26, } /** - 类型是一个对象 - key对应fruitCount的key - value 是 number 类型 **/ type SingleFruitCount = any//怎么定义❓ const singleFruitCount: SingleFruitCount = { banana: 12, }
你可能会想到以下两个方案
//方案1 type SingleFruitCount = { [k in keyof typeof fruitCount]?:number } //方案2 type SingleFruitCount = | { apple: number; } | { banana: number; } | { pear: number; }
方案1看起来更简洁并且可以满足我们的需要,但是他是一个
partial并不是一个union类型,union跟partial相比有更多的转换能力,我们会在下一个tips中体现。让我们回到方案2,方案2虽然能满足需求,但是看起来并不那么优雅,所以让我们改进一下,先从
fruitCounts对象中创建一个FruitCount类型,然后我将衍生出一个新的类型NewSingleFruitCounttype FruitCounts = typeof fruitCounts type NewSingleFruitCount = { [K in keyof FruitCounts]: {} } /** 它将 FruitCounts 的每个属性值设置为一个空对象 因此,当我们使用它时,TypeScript将期待一个像这样的效果👇🏻 **/ const singleFruitCount: NewSingleFruitCount = { apple: {}, pear: {}, banana: {} }
但是我们期望属性值的类型是
number,我们进行下一步改进type NewSingleFruitCount = { [K in keyof FruitCounts]: { [K2 in K]: number } } //效果如下👇🏻 const singleFruitCount: NewSingleFruitCount = { apple: { apple: 2, }, pear: { pear: 4, }, banana: { banana: 26, }, }
最后,我们通过映射
NewSingleFruitCount类型,来获取真实的值type NewSingleFruitCount = { [K in keyof FruitCounts]: { [K2 in K]: number } }[keyof FruitCounts]
这样就可以获取到真实的结果🎉
const singleFruitCount: NewSingleFruitCount = { apple: 2, }
const singleFruitCount:SingleFruitCount = {}//期望 ts 能够报错,但是它并不会报错 type SingleFruitCount = { [k in keyof typeof fruitCount]?:number }
End of Article